import { _decorator, Component, Node, v3, BoxCollider2D, Size, UITransform, Vec3, clamp } from 'cc';
import { GlobalConfig } from '../../Init/Config/GlobalConfig';
import { GlobalEnum } from '../../Init/Config/GlobalEnum';
import { GlobalTmpData } from '../../Init/Config/GlobalTmpData';
import EventManager from '../../Init/Managers/EventManager';
import { EventTypes } from '../../Init/Managers/EventTypes';
import { AudioEnum } from '../../Init/SystemAudio/AudioEnum';
import { AudioSystem } from '../../Init/SystemAudio/AudioSystem';
import { StorageSystem } from '../../Init/SystemStorage/StorageSystem';
import { BasicEnemy, EnemyAlive, EnemyDeath } from './BasicEnemy';
import { EnemyBarrier } from './EnemyBarrier';
const { ccclass, property } = _decorator;

@ccclass('Tank2D')
export class Tank2D extends BasicEnemy {
    public atk = GlobalConfig.Tank.atk;
    public atkCd = 1 / GlobalConfig.Tank.atkSpd;
    public checkDist = GlobalConfig.Tank.checkDist;
    public maxHp = 0;

    public init(d): void {
        super.init();
        this.enemyType = GlobalEnum.EnemyTypes.Tank;

        // 血量攻击加成
        let lv = StorageSystem.getData().levelAssets.curLv;
        let atkLvRate = lv < 3 ? GlobalConfig.Enemy.guideLvRate : GlobalConfig.Enemy.atkLvRate;
        this.atk = GlobalConfig.Tank.atk;
        this.atk *= (1 + (lv - 1) * atkLvRate);

        this.hp = GlobalConfig.Tank.HP;
        this.hp += Math.floor(lv / GlobalConfig.Enemy.hpStepLv) * GlobalConfig.Enemy.hpStep;
        this.hp = clamp(Math.floor(this.hp), GlobalConfig.Tank.HP, GlobalConfig.Enemy.hpMax);

        this.aimNum = this.hp;
        this.maxHp = this.hp;
        this.atkCd = 1 / GlobalConfig.Tank.atkSpd;
        this.checkDist = GlobalConfig.Tank.checkDist;
        //
        this.mappingProps.node = this.node;
        this.mappingProps.enemyType = this.enemyType;
        this.mappingProps.enemyName = d.enemyName;
        this.node[GlobalEnum.ExtralProp.customProps] = { hp: this.hp, maxHp: this.maxHp, state: GlobalEnum.TankClips.Idle };

        //初始化碰撞体
        const cmp = this.node.getComponent(EnemyBarrier);
        cmp.setData(d);
    }

    public setBodySize(s: Size) {
        let trans = this.node.getComponent(UITransform);
        trans.setContentSize(s);

        let body = this.node.getComponent(BoxCollider2D);
        if (body) {
            body.size = s;
            body.apply();
        }
    }

    public update(dt: any): void {
        super.update(dt);
        //更新血量
        this.node[GlobalEnum.ExtralProp.customProps].hp = this.hp;
        this.node[GlobalEnum.ExtralProp.customProps].maxHp = this.maxHp;
    }

    /**设置初始状态 */
    protected setStateData() {
        this._stateRecs[GlobalEnum.EnemyState.Alive] = new TankAlive(this);
        this._stateRecs[GlobalEnum.EnemyState.Death] = new TankDeath(this);

        setTimeout(() => {
            this.changeState(GlobalEnum.EnemyState.Alive);
        }, 0);
    }
}

export class TankAlive extends EnemyAlive {
    public cmp: Tank2D = null;
    //------旋转
    public _rotVec = v3();
    //目标弧度
    public _toRadianY = 0;
    //初始弧度
    public _curRadianY = -Math.PI * 0.5;
    //旋转方向 
    public _rotDirec = 1;
    //旋转速度
    public _rotSpd = Math.PI * 4;
    //

    constructor(c) {
        super(c);
        this.cmp = c;
        this.atkCd = this.cmp.atkCd;

    }

    private tmpP = v3();
    public checkZombies(dt) {
        this.checkTime += dt;
        if (this.checkTime >= this.checkCd) {
            this.checkTime = 0;

            //检测信息玩家touchPlayer 位置
            const wp = GlobalTmpData.Player.wpos2D;
            this.tmpP.set(wp).subtract(this.cmp.node.worldPosition);
            this.isInArea = this.tmpP.length() <= this.cmp.checkDist;
            if (this.isInArea) {
                this.onChecked();
                this.cmp.node[GlobalEnum.ExtralProp.customProps].state = GlobalEnum.TankClips.Atk;
            } else {
                this.cmp.node[GlobalEnum.ExtralProp.customProps].state = GlobalEnum.TankClips.Idle;
            }
        }
    }

    public onChecked(): void {
        this.tmpP.set(GlobalTmpData.Player.wpos2D).subtract(this.cmp.node.worldPosition);
        this.calRotation(Math.atan2(this.tmpP.y, this.tmpP.x));

        EventManager.emit(EventTypes.RoleEvents.ShowDialog, GlobalEnum.DialogTargetType.TankBoss);
    }

    public update(dt: any): void {
        super.update(dt);
        this.rotation(dt);
    }

    //旋转2d
    public rotation(dt) {
        if (this._curRadianY !== this._toRadianY) {
            let step = this._rotSpd * dt;
            if (step > Math.abs(this._curRadianY - this._toRadianY)) {
                this._curRadianY = this._toRadianY;
            } else {
                step *= this._rotDirec;
                this._curRadianY += step;
            }
            this._rotVec.set(0, 0, this._curRadianY * 57.3);
            this.cmp.node.eulerAngles = this._rotVec;
        }
    }

    private _tmpP = v3();
    private _tmpV = v3();
    public onAtk(): void {
        let t = this.tmpP.length() / GlobalConfig.Missile.spd; //爆炸时间
        //发射特效+导弹
        EventManager.emit(EventTypes.EffectEvents.ShowTankShootEffect, { uuid: this.cmp.node.uuid, toP: GlobalTmpData.Player.lpos3D, t: t });

        //发射导弹2d
        EventManager.emit(EventTypes.EnemyEvents.ShootMissile,
            { p: this.cmp.node.position, toP: GlobalTmpData.Player.lpos2D, atk: this.cmp.atk, t: t });

        //显示导弹终点位置        
        this.tmpP.set(GlobalTmpData.Player.lpos2D).subtract(this.cmp.node.position);
        EventManager.emit(EventTypes.EffectEvents.ShowBoomErea, {
            p: v3(GlobalTmpData.Player.lpos3D),
            s: GlobalConfig.Missile.atkRadius * 2 * GlobalConfig.Scale2DTo3D,
            t: t
        });

    }
    //根据目标旋转角度计算出旋转方式-弧度计算
    public calRotation(r: number) {
        this._toRadianY = r;
        //1.0 将当前角色角度+目标角度转换到360之内-弧度计算
        const pi = Math.PI;
        if (this._toRadianY < 0) {
            this._toRadianY += pi * 2;
        }
        this._curRadianY = this._curRadianY % (pi * 2);
        if (this._curRadianY > pi * 2) {
            this._toRadianY -= pi * 2;
        } else if (this._curRadianY < 0) {
            this._toRadianY += pi * 2;
        }
        //2.0 判断差值范围
        let sub = this._toRadianY - this._curRadianY;
        if (sub > pi) {
            //反向
            this._curRadianY += pi * 2;
            this._rotDirec = -1;
        } else if (sub < -pi) {
            //反向
            this._toRadianY += pi * 2;
            this._rotDirec = 1;
        } else if (sub > 0) {
            this._rotDirec = 1;
        } else if (sub < 0) {
            this._rotDirec = -1;
        }
    }
}

export class TankDeath extends EnemyDeath {
    private _tmpP = v3();

    public enter(d: { isChange: boolean; finishCb: Function; }): void {
        super.enter(d);
        this.cmp.node[GlobalEnum.ExtralProp.customProps].state = GlobalEnum.TankClips.Death;

        AudioSystem.playEffect(AudioEnum.Boom);
        GlobalTmpData.Player.kill.boss++;
    }
    tmpV3 = v3();
    protected onFinish() {
        super.onFinish();
        //奖励
        // this.tmpV3.set(this.cmp.node.position.x * GlobalConfig.Scale2DTo3D, 1, -this.cmp.node.position.y * GlobalConfig.Scale2DTo3D);
        // EventManager.emit(EventTypes.UIEvents.AddGoldEffect, { wpos: this.tmpV3, gold: GlobalConfig.Award.boss, isAnim: false });
    }
}
